/*******************************************************************************
 * Copyright (c) 2004, 2007 Actuate Corporation.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License 2.0 which is available at
 * https://www.eclipse.org/legal/epl-2.0/.
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 *
 * Contributors:
 *  Actuate Corporation  - initial API and implementation
 *******************************************************************************/

package org.eclipse.birt.report.designer.ui.dialogs;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.eclipse.birt.core.exception.BirtException;
import org.eclipse.birt.report.data.adapter.api.DataModelAdapterStatus;
import org.eclipse.birt.report.data.adapter.api.DataModelAdapterUtil;
import org.eclipse.birt.report.data.adapter.api.LinkedDataSetUtil;
import org.eclipse.birt.report.designer.core.model.SessionHandleAdapter;
import org.eclipse.birt.report.designer.data.ui.dataset.DataSetUIUtil;
import org.eclipse.birt.report.designer.internal.ui.dialogs.DataColumnBindingDialog;
import org.eclipse.birt.report.designer.internal.ui.dialogs.IBindingDialogHelper;
import org.eclipse.birt.report.designer.internal.ui.extension.ExtendedDataModelUIAdapterHelper;
import org.eclipse.birt.report.designer.internal.ui.util.DataUtil;
import org.eclipse.birt.report.designer.internal.ui.util.ExceptionHandler;
import org.eclipse.birt.report.designer.internal.ui.util.ExpressionUtility;
import org.eclipse.birt.report.designer.internal.ui.util.IHelpContextIds;
import org.eclipse.birt.report.designer.internal.ui.util.UIUtil;
import org.eclipse.birt.report.designer.internal.ui.util.WidgetUtil;
import org.eclipse.birt.report.designer.nls.Messages;
import org.eclipse.birt.report.designer.ui.views.ElementAdapterManager;
import org.eclipse.birt.report.designer.ui.views.attributes.providers.ChoiceSetFactory;
import org.eclipse.birt.report.designer.ui.views.attributes.providers.LinkedDataSetAdapter;
import org.eclipse.birt.report.designer.util.DEUtil;
import org.eclipse.birt.report.model.api.CachedMetaDataHandle;
import org.eclipse.birt.report.model.api.CommandStack;
import org.eclipse.birt.report.model.api.ComputedColumnHandle;
import org.eclipse.birt.report.model.api.DataItemHandle;
import org.eclipse.birt.report.model.api.DataSetHandle;
import org.eclipse.birt.report.model.api.DataSetParameterHandle;
import org.eclipse.birt.report.model.api.DesignElementHandle;
import org.eclipse.birt.report.model.api.GroupHandle;
import org.eclipse.birt.report.model.api.ImageHandle;
import org.eclipse.birt.report.model.api.ReportItemHandle;
import org.eclipse.birt.report.model.api.ResultSetColumnHandle;
import org.eclipse.birt.report.model.api.StructureFactory;
import org.eclipse.birt.report.model.api.activity.SemanticException;
import org.eclipse.birt.report.model.api.elements.structures.ComputedColumn;
import org.eclipse.birt.report.model.api.metadata.IChoiceSet;
import org.eclipse.birt.report.model.api.metadata.PropertyValueException;
import org.eclipse.birt.report.model.api.util.StringUtil;
import org.eclipse.birt.report.model.elements.interfaces.IReportItemModel;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.CheckStateChangedEvent;
import org.eclipse.jface.viewers.CheckboxTableViewer;
import org.eclipse.jface.viewers.ICheckStateListener;
import org.eclipse.jface.viewers.ILabelProviderListener;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CLabel;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.PlatformUI;

/**
 * The dialog to select and edit column bindings
 */

public class ColumnBindingDialog extends BaseDialog {

	public static class BindingInfo {

		private int bindingType;
		private Object bindingValue;

		public BindingInfo() {
		}

		public BindingInfo(int type, Object value) {
			this.bindingType = type;
			this.bindingValue = value;
		}

		public int getBindingType() {
			return bindingType;
		}

		public Object getBindingValue() {
			return bindingValue;
		}

		public void setBindingType(int bindingType) {
			this.bindingType = bindingType;
		}

		public void setBindingValue(Object bindingValue) {
			this.bindingValue = bindingValue;
		}
	}

	private static final String ALL = Messages.getString("ColumnBindingDialog.All");//$NON-NLS-1$

	private static final String CHOICE_DATASET_FROM_CONTAINER = Messages
			.getString("ColumnBindingDialog.Choice.DatasetFromContainer");//$NON-NLS-1$

	private static final String CHOICE_NONE = Messages.getString("ColumnBindingDialog.NONE");//$NON-NLS-1$

	private static final String CHOICE_REPORTITEM_FROM_CONTAINER = Messages
			.getString("ColumnBindingDialog.Choice.ReportItemFromContainer");//$NON-NLS-1$

	private static final String COLUMN_AGGREGATEON = Messages.getString("ColumnBindingDialog.Column.AggregateOn"); //$NON-NLS-1$

	private static final String COLUMN_FILTER = Messages.getString("ColumnBindingDialog.Column.Filter"); //$NON-NLS-1$

	private static final String COLUMN_FUNCTION = Messages.getString("ColumnBindingDialog.Column.Function"); //$NON-NLS-1$

	private static final String COLUMN_DATATYPE = Messages.getString("ColumnBindingDialog.Column.DataType"); //$NON-NLS-1$

	private static final String COLUMN_DISPLAYNAME = Messages.getString("ColumnBindingDialog.Column.DisplayName"); //$NON-NLS-1$

	private static final String COLUMN_DISPLAYNAME_ID = Messages.getString("ColumnBindingDialog.Column.DisplayNameID"); //$NON-NLS-1$

	private static final String COLUMN_EXPRESSION = Messages.getString("ColumnBindingDialog.Column.Expression"); //$NON-NLS-1$

	// private static final String BUTTON_GENERATE = Messages.getString(
	// "ColumnBindingDialog.Button.Generate" ); //$NON-NLS-1$
	private static final String COLUMN_NAME = Messages.getString("ColumnBindingDialog.Column.Name"); //$NON-NLS-1$

	private static final IChoiceSet DATA_TYPE_CHOICE_SET = DEUtil.getMetaDataDictionary()
			.getStructure(ComputedColumn.COMPUTED_COLUMN_STRUCT).getMember(ComputedColumn.DATA_TYPE_MEMBER)
			.getAllowedChoices();

	public static final String DEFAULT_DLG_TITLE = Messages.getString("ColumnBindingDialog.DialogTitle"); //$NON-NLS-1$

	private static final String dummyChoice = "dummy"; //$NON-NLS-1$

	private static final String INPUT_PROPMT = Messages.getString("ColumnBindingDialog.InputPrompt"); //$NON-NLS-1$

	private static final String LABEL_COLUMN_BINDINGS = Messages.getString("ColumnBindingDialog.Label.DataSet"); //$NON-NLS-1$

	private static final String MSG_ADD = Messages.getString("ColumnBindingDialog.Text.Add"); //$NON-NLS-1$

	private static final String MSG_DELETE = Messages.getString("ColumnBindingDialog.Text.Del"); //$NON-NLS-1$

	private static final String MSG_REFRESH = Messages.getString("ColumnBindingDialog.Text.Refresh"); //$NON-NLS-1$

	private static final String MSG_ADDAGGREGATEON = Messages.getString("ColumnBindingDialog.Text.AddAggr"); //$NON-NLS-1$

	private static final String MSG_EDIT = Messages.getString("ColumnBindingDialog.Text.Edit"); //$NON-NLS-1$

	private static final String NONE_AGGREGATEON = Messages.getString("ColumnBindingDialog.AGGREGATEON.NONE");//$NON-NLS-1$

	private static final String WARN_COLUMN_BINDINGS = Messages.getString("ColumnBingingDialog.Label.Warn"); //$NON-NLS-1$

	// private Button generateButton;
	protected TableViewer bindingTable;

	protected Button btnAdd;

	// private List bindingList;

	protected Button btnDel;

	protected Button btnEdit;

	private boolean canAggregate = false;

	// true if the binding column can be changed, or false if not.
	private boolean canSelect = false;

	private Composite composite;

	private IStructuredContentProvider contentProvider = new IStructuredContentProvider() {

		@Override
		public void dispose() {
		}

		@Override
		public Object[] getElements(Object inputElement) {
			List elementsList = getBindingList((DesignElementHandle) inputElement);
			Object[] arrays = elementsList.toArray();
			Arrays.sort(arrays, new BindingComparator());
			return arrays;
		}

		@Override
		public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
		}
	};

	private class BindingComparator implements Comparator {

		@Override
		public int compare(Object o1, Object o2) {
			ComputedColumnHandle binding1 = (ComputedColumnHandle) o1;
			ComputedColumnHandle binding2 = (ComputedColumnHandle) o2;
			String columnText1 = labelProvider.getColumnText(binding1, sortingColumnIndex);
			String columnText2 = labelProvider.getColumnText(binding2, sortingColumnIndex);
			int result = (columnText1 == null ? "" : columnText1).compareTo((columnText2 == null ? "" : columnText2));
			if (sortDirection == SWT.UP) {
				return result;
			} else {
				return 0 - result;
			}
		}
	}

	protected int getOriginalIndex(int pos) {
		List children = new ArrayList();
		for (Iterator iter = getBindingList((DesignElementHandle) inputElement).iterator(); iter.hasNext();) {
			children.add(iter.next());
		}

		Object[] arrays = children.toArray();
		Arrays.sort(arrays, new BindingComparator());
		return children.indexOf(Arrays.asList(arrays).get(pos));
	}

	protected int getShowIndex(int pos) {
		List children = new ArrayList();
		for (Iterator iter = getBindingList((DesignElementHandle) inputElement).iterator(); iter.hasNext();) {
			children.add(iter.next());
		}

		Object[] arrays = children.toArray();
		Arrays.sort(arrays, new BindingComparator());
		return Arrays.asList(arrays).indexOf(children.get(pos));
	}

	private Combo datasetCombo;

	private Button datasetRadio;

	private transient boolean enableAutoCommit = false;

	protected ExpressionProvider expressionProvider;

	private List groupList = Collections.EMPTY_LIST;

	private String[] groups;

	protected ReportItemHandle inputElement;

	private boolean isDataSetVisible;

	private ITableLabelProvider labelProvider = new ITableLabelProvider() {

		@Override
		public void addListener(ILabelProviderListener listener) {
		}

		@Override
		public void dispose() {
		}

		@Override
		public Image getColumnImage(Object element, int columnIndex) {
			return null;
		}

		@Override
		public String getColumnText(Object element, int columnIndex) {
			if (element == dummyChoice) {
				if (columnIndex == 1) {
					return INPUT_PROPMT;
				}
				return ""; //$NON-NLS-1$
			}
			ComputedColumnHandle handle = ((ComputedColumnHandle) element);
			String text = null;

			switch (columnIndex) {
			case 1:
				text = handle.getName();
				break;
			case 2:
				text = handle.getDisplayNameID();
				break;
			case 3:
				text = handle.getDisplayName();
				break;
			case 4:
				text = ChoiceSetFactory.getDisplayNameFromChoiceSet(handle.getDataType(), DATA_TYPE_CHOICE_SET);
				break;
			case 5:
				text = org.eclipse.birt.report.designer.data.ui.util.DataUtil.getAggregationExpression(handle);
				break;
			case 6:
				try {
					String function = handle.getAggregateFunction();
					if (function != null) {
						if (org.eclipse.birt.report.designer.data.ui.util.DataUtil.getAggregationManager()
								.getAggregation(function) != null) {
							text = org.eclipse.birt.report.designer.data.ui.util.DataUtil.getAggregationManager()
									.getAggregation(function).getDisplayName();
						}
					}
				} catch (BirtException e) {
					ExceptionHandler.handle(e);
				}
				break;
			case 7:
				text = handle.getFilterExpression();
				break;
			case 8:
				String value = DEUtil.getAggregateOn(handle);
				if (value == null) {
					if (handle.getAggregateFunction() != null) {
						text = ALL;
					} else {
						text = NONE_AGGREGATEON;
					}
				} else {
					text = value;
				}

				break;
			}

			if (text == null) {
				text = ""; //$NON-NLS-1$
			}
			return text;
		}

		@Override
		public boolean isLabelProperty(Object element, String property) {
			return false;
		}

		@Override
		public void removeListener(ILabelProviderListener listener) {
		}

	};

	private String NullDatasetChoice = null;

	private String NullReportItemChoice = null;

	private Combo reportItemCombo;

	private Button reportItemRadio;

	private String selectedColumnName = null;

	private int selectIndex;

	private CLabel warnLabel;

	private boolean filterSelf;

	public ColumnBindingDialog(ReportItemHandle input) {
		super(DEFAULT_DLG_TITLE);
		setInput(input);
	}

	public ColumnBindingDialog(ReportItemHandle input, boolean canSelect) {
		super(DEFAULT_DLG_TITLE);
		setInput(input);
		this.canSelect = canSelect;

	}

	public ColumnBindingDialog(ReportItemHandle input, Shell parent, boolean canSelect) {
		this(input, parent, DEFAULT_DLG_TITLE, canSelect, true);
	}

	public ColumnBindingDialog(ReportItemHandle input, Shell parent, boolean canSelect, boolean canAggregate) {
		this(input, parent, DEFAULT_DLG_TITLE, canSelect, canAggregate);
	}

	public ColumnBindingDialog(ReportItemHandle input, Shell parent, String title, boolean canSelect,
			boolean canAggregate) {
		super(parent, title);
		setInput(input);
		this.canSelect = canSelect;
		this.canAggregate = canAggregate;
	}

	public ColumnBindingDialog(ReportItemHandle input, String title) {
		super(title);
		setInput(input);
	}

	public ColumnBindingDialog(ReportItemHandle input, String title, boolean canAggregate) {
		super(title);
		setInput(input);
		this.canAggregate = canAggregate;
	}

	/**
	 * @param input
	 * @param title
	 * @param canAggregate
	 * @param canSelect
	 * @param filterSelf   don't show input item handle's binding
	 */
	public ColumnBindingDialog(ReportItemHandle input, String title, boolean canAggregate, boolean canSelect,
			boolean filterSelf) {
		super(title);
		setInput(input);
		this.canSelect = canSelect;
		this.canAggregate = canAggregate;
		this.filterSelf = filterSelf;
	}

	protected void addBinding(ComputedColumn column) {
		try {
			DEUtil.addColumn(DEUtil.getBindingHolder(inputElement), column, false);
		} catch (SemanticException e) {
			ExceptionHandler.handle(e);
		}
	}

	private void generateOutputParmsBindings(DataSetHandle datasetHandle) {
		List<DataSetParameterHandle> outputParams = new ArrayList<>();
		for (Iterator iter = datasetHandle.parametersIterator(); iter.hasNext();) {
			Object obj = iter.next();
			if ((obj instanceof DataSetParameterHandle) && ((DataSetParameterHandle) obj).isOutput()) {
				outputParams.add((DataSetParameterHandle) obj);
			}
		}

		int ret = -1;
		if (outputParams.size() > 0) {
			MessageDialog prefDialog = new MessageDialog(UIUtil.getDefaultShell(),
					Messages.getString("dataBinding.title.generateOutputParam"), //$NON-NLS-1$
					null, Messages.getString("dataBinding.msg.generateOutputParam"), //$NON-NLS-1$
					MessageDialog.QUESTION, new String[] { Messages.getString("AttributeView.dialg.Message.Yes"), //$NON-NLS-1$
							Messages.getString("AttributeView.dialg.Message.No") }, //$NON-NLS-1$
					0);// $NON-NLS-1$

			ret = prefDialog.open();
		}

		if (ret == 0) {
			for (int i = 0; i < outputParams.size(); i++) {
				DataSetParameterHandle param = outputParams.get(i);
				ComputedColumn bindingColumn = StructureFactory.newComputedColumn(inputElement, param.getName());
				bindingColumn.setDataType(param.getDataType());
				ExpressionUtility.setBindingColumnExpression(param, bindingColumn, true);

				try {
					inputElement.addColumnBinding(bindingColumn, false);
				} catch (SemanticException e) {
					ExceptionHandler.handle(e);
				}
			}
		}
	}

	/**
	 * Adds buttons in Button area.
	 *
	 * @param cmp   parent composite
	 * @param table the Table widget affected by Buttons
	 * @return the number of added buttons
	 */
	protected int addButtons(Composite cmp, final Table table) {
		btnRefresh = new Button(cmp, SWT.PUSH);
		btnRefresh.setText(MSG_REFRESH);
		GridData data = new GridData(GridData.VERTICAL_ALIGN_BEGINNING);
		data.widthHint = Math.max(60, btnRefresh.computeSize(SWT.DEFAULT, SWT.DEFAULT, true).x);
		btnRefresh.setLayoutData(data);
		btnRefresh.addListener(SWT.Selection, new Listener() {

			@Override
			public void handleEvent(Event event) {
				if (inputElement != null) {
					DataSetHandle datasetHandle = inputElement.getDataSet();
					if (datasetHandle != null) {
						try {
							CachedMetaDataHandle cmdh = DataSetUIUtil.getCachedMetaDataHandle(datasetHandle);
							for (Iterator iter = cmdh.getResultSet().iterator(); iter.hasNext();) {
								ResultSetColumnHandle element = (ResultSetColumnHandle) iter.next();
								ComputedColumn bindingColumn = StructureFactory.newComputedColumn(inputElement,
										element.getColumnName());
								bindingColumn.setDataType(element.getDataType());
								ExpressionUtility.setBindingColumnExpression(element, bindingColumn);

								inputElement.addColumnBinding(bindingColumn, false);

							}
						} catch (SemanticException e) {
							ExceptionHandler.handle(e);
						}
						refreshBindingTable();
						updateButtons();
					}
				}
			}
		});
		return 1;
	}

	private void commit() {
		if (isEnableAutoCommit()) {
			getActionStack().commit();
		}
	}

	@Override
	protected Control createDialogArea(Composite parent) {

		UIUtil.bindHelp(parent, IHelpContextIds.COLUMNBINDING_DIALOG_ID);
		Composite parentComposite = (Composite) super.createDialogArea(parent);

		if (this.canSelect) {
			composite = new Composite(parentComposite, SWT.NONE);
			composite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
			composite.setLayout(UIUtil.createGridLayoutWithoutMargin(2, false));

			warnLabel = new CLabel(composite, SWT.NONE);
			warnLabel.setImage(PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJS_WARN_TSK));
			warnLabel.setText(WARN_COLUMN_BINDINGS);
			GridData gd = new GridData(GridData.FILL_HORIZONTAL);
			gd.horizontalSpan = 2;
			warnLabel.setLayoutData(gd);

			datasetRadio = new Button(composite, SWT.RADIO);
			datasetRadio.setText(LABEL_COLUMN_BINDINGS);
			datasetRadio.setLayoutData(new GridData(GridData.BEGINNING));
			datasetRadio.addSelectionListener(new SelectionAdapter() {

				@Override
				public void widgetSelected(SelectionEvent e) {
					refreshBinding();
					if (datasetRadio.getSelection()
							&& inputElement.getDataBindingType() == ReportItemHandle.DATABINDING_TYPE_REPORT_ITEM_REF
							&& (DEUtil.getBindingHolder(inputElement, true) == null || DEUtil
									.getBindingHolder(inputElement, true)
									.getDataBindingType() != ReportItemHandle.DATABINDING_TYPE_REPORT_ITEM_REF)) {
						saveBinding();
					}
				}

			});

			datasetCombo = new Combo(composite, SWT.READ_ONLY | SWT.BORDER);
			datasetCombo
					.setBackground(PlatformUI.getWorkbench().getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND));
			datasetCombo.setVisibleItemCount(30);
			String[] dataSets = ChoiceSetFactory.getDataSets();
			String[] newList = new String[dataSets.length + 1];
			newList[0] = NullDatasetChoice;
			System.arraycopy(dataSets, 0, newList, 1, dataSets.length);
			datasetCombo.setItems(newList);
			String dataSetName = getDataSetName();
			datasetCombo.deselectAll();

			if (dataSetName != null) {
				datasetCombo.setText(dataSetName);
			} else {
				datasetCombo.select(0);
			}

			gd = new GridData();
			gd.widthHint = 250;
			datasetCombo.setLayoutData(gd);
			datasetCombo.addSelectionListener(new SelectionAdapter() {

				@Override
				public void widgetSelected(SelectionEvent event) {
					saveBinding();
				}
			});

			reportItemRadio = new Button(composite, SWT.RADIO);
			reportItemRadio.setText(Messages.getString("BindingPage.ReportItem.Label")); //$NON-NLS-1$
			reportItemRadio.addSelectionListener(new SelectionAdapter() {

				@Override
				public void widgetSelected(SelectionEvent e) {
					refreshBinding();
					if (reportItemRadio.getSelection()
							&& inputElement.getDataBindingType() == ReportItemHandle.DATABINDING_TYPE_DATA
							&& (DEUtil.getBindingHolder(inputElement, true) == null || DEUtil
									.getBindingHolder(inputElement, true)
									.getDataBindingType() == ReportItemHandle.DATABINDING_TYPE_REPORT_ITEM_REF)) {
						saveBinding();
					}
				}
			});
			reportItemCombo = new Combo(composite, SWT.READ_ONLY | SWT.BORDER);
			reportItemCombo
					.setBackground(PlatformUI.getWorkbench().getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND));
			reportItemCombo.setVisibleItemCount(30);
			gd = new GridData();
			gd.widthHint = 250;
			reportItemCombo.setLayoutData(gd);
			reportItemCombo.addSelectionListener(new SelectionAdapter() {

				@Override
				public void widgetSelected(SelectionEvent e) {
					saveBinding();
				}
			});
		}

		Composite contentComposite = new Composite(parentComposite, SWT.NONE);
		contentComposite.setLayoutData(new GridData(GridData.FILL_BOTH));
		contentComposite.setLayout(UIUtil.createGridLayoutWithoutMargin(2, false));
		/**
		 * Binding table
		 */
		final Table table = new Table(contentComposite,
				SWT.SINGLE | SWT.FULL_SELECTION | SWT.BORDER | (canSelect ? SWT.CHECK : 0));
		GridData gd = new GridData(GridData.FILL_BOTH);
		gd.heightHint = 200;
		gd.verticalSpan = 5;
		table.setLayoutData(gd);
		table.setLinesVisible(true);
		table.setHeaderVisible(true);

		Listener sortListener = new Listener() {

			@Override
			public void handleEvent(Event e) {
				int modelPos = -1;
				if (table.getSelectionIndex() > -1) {
					modelPos = getOriginalIndex(table.getSelectionIndex());
				}
				// determine new sort column and direction
				TableColumn sortColumn = table.getSortColumn();
				TableColumn currentColumn = (TableColumn) e.widget;
				int dir = table.getSortDirection();
				if (sortColumn == currentColumn) {
					dir = dir == SWT.UP ? SWT.DOWN : SWT.UP;
				} else {
					table.setSortColumn(currentColumn);
					dir = SWT.UP;
					for (int i = 0; i < table.getColumnCount(); i++) {
						if (currentColumn == table.getColumn(i)) {
							setSortingColumnIndex(i);
							break;
						}
					}
				}
				// update data displayed in table
				setSortDirection(dir);
				table.setSortDirection(dir);
				refreshBindingTable();
				if (modelPos > -1) {
					table.setSelection(getShowIndex(modelPos));
				}
			}

		};

		// table.addKeyListener( new KeyAdapter( ) {
		//
		// /**
		// * @see
		// org.eclipse.swt.events.KeyAdapter#keyReleased(org.eclipse.swt.events.
		// KeyEvent)
		// */
		// public void keyReleased( KeyEvent e )
		// {
		// // If Delete pressed, delete the selected row
		// if ( e.keyCode == SWT.DEL )
		// {
		// IStructuredSelection selection = (IStructuredSelection)
		// bindingTable.getSelection( );
		// if ( selection.getFirstElement( ) instanceof ComputedColumnHandle )
		// {
		// deleteRow( (ComputedColumnHandle) selection.getFirstElement( ) );
		// }
		// }
		// }
		// } );

		table.addKeyListener(new KeyAdapter() {

			@Override
			public void keyPressed(KeyEvent e) {
				if (e.keyCode == SWT.DEL && (DEUtil.getBindingHolder(inputElement)
						.getDataBindingType() == ReportItemHandle.DATABINDING_TYPE_DATA
						|| (DEUtil.getBindingHolder(inputElement)
								.getDataBindingType() == ReportItemHandle.DATABINDING_TYPE_NONE
								&& (DEUtil.getBindingHolder(inputElement, true) == null || DEUtil
										.getBindingHolder(inputElement, true)
										.getDataBindingType() != ReportItemHandle.DATABINDING_TYPE_REPORT_ITEM_REF)))) {
					int itemCount = table.getItemCount();
					if (selectIndex == itemCount) {
						return;
					}
					if (selectIndex == itemCount - 1) {
						selectIndex--;
					}
					try {
						handleDelEvent();
					} catch (Exception e1) {
						WidgetUtil.processError(getShell(), e1);
					}
					refreshBindingTable();
				}
			}
		});

		table.addSelectionListener(new SelectionAdapter() {

			@Override
			public void widgetSelected(SelectionEvent e) {
				selectIndex = table.getSelectionIndex();
				updateButtons();
			}
		});

		table.addMouseListener(new MouseAdapter() {

			/**
			 * @param e
			 */
			@Override
			public void mouseDoubleClick(MouseEvent e) {
				editSelectedBinding(table.getSelectionIndex());
				refreshBindingTable();
			}
		});
		String[] columns = null;
		int[] columnWidth = null;

		groups = new String[groupList.size() + 1];
		groups[0] = ALL;
		for (int i = 0; i < groupList.size(); i++) {
			groups[i + 1] = ((GroupHandle) groupList.get(i)).getName();
		}

		if (canAggregate) {
			columns = new String[] { null, COLUMN_NAME, COLUMN_DISPLAYNAME_ID, COLUMN_DISPLAYNAME, COLUMN_DATATYPE,
					COLUMN_EXPRESSION, COLUMN_FUNCTION, COLUMN_FILTER, COLUMN_AGGREGATEON };
			columnWidth = new int[] { canSelect ? 25 : 20, 100, 100, 100, 70, 100, 100, 100, 100 };
		} else {
			columns = new String[] { null, COLUMN_NAME, COLUMN_DISPLAYNAME_ID, COLUMN_DISPLAYNAME, COLUMN_DATATYPE,
					COLUMN_EXPRESSION };
			columnWidth = new int[] { canSelect ? 25 : 20, 120, 120, 120, 70, 120 };
		}

		for (int i = 0; i < columns.length; i++) {
			TableColumn column = new TableColumn(table, SWT.LEFT);
			if (i == 0) {
				table.setSortColumn(column);
			}
			column.setResizable(columns[i] != null);
			if (columns[i] != null) {
				column.setText(columns[i]);
			}
			column.setWidth(columnWidth[i]);
			column.addListener(SWT.Selection, sortListener);
		}
		table.setSortDirection(SWT.UP);

		if (canSelect) {
			bindingTable = new CheckboxTableViewer(table);
			((CheckboxTableViewer) bindingTable).addCheckStateListener(new ICheckStateListener() {

				@Override
				public void checkStateChanged(CheckStateChangedEvent event) {

					if (event.getElement() instanceof ComputedColumnHandle) {
						ComputedColumnHandle handle = (ComputedColumnHandle) event.getElement();
						if (handle.getName().equals(selectedColumnName)) {
							selectedColumnName = null;
						} else {
							selectedColumnName = handle.getName();
						}
						updateSelection();
						updateButtons();
					} else {
						((CheckboxTableViewer) bindingTable).setChecked(dummyChoice, false);
					}
				}
			});
		} else {
			bindingTable = new TableViewer(table);
		}
		bindingTable.setColumnProperties(columns);
		bindingTable.setContentProvider(contentProvider);
		bindingTable.setLabelProvider(labelProvider);
		// bindingTable.setCellModifier( cellModifier );
		bindingTable.setInput(inputElement);

		bindingTable.addSelectionChangedListener(new ISelectionChangedListener() {

			@Override
			public void selectionChanged(SelectionChangedEvent event) {
				updateButtons();
			}

		});

		btnAdd = new Button(contentComposite, SWT.PUSH);
		btnAdd.setText(MSG_ADD);
		GridData data = new GridData();
		data.widthHint = Math.max(60, btnAdd.computeSize(SWT.DEFAULT, SWT.DEFAULT, true).x);
		btnAdd.setLayoutData(data);
		btnAdd.addSelectionListener(new SelectionAdapter() {

			@Override
			public void widgetSelected(SelectionEvent e) {
				handleAddEvent();
				refreshBindingTable();
				if (table.getItemCount() > 0) {
					selectIndex = getShowIndex(table.getItemCount() - 1);
				}
				updateButtons();
			}

		});

		if (canAggregate) {
			btnAddAggr = new Button(contentComposite, SWT.PUSH);
			btnAddAggr.setText(MSG_ADDAGGREGATEON); // $NON-NLS-1$
			data = new GridData();
			data.widthHint = Math.max(60, btnAddAggr.computeSize(SWT.DEFAULT, SWT.DEFAULT, true).x);
			btnAddAggr.setLayoutData(data);
			btnAddAggr.addListener(SWT.Selection, new Listener() {

				@Override
				public void handleEvent(Event event) {
					DataColumnBindingDialog dialog = new DataColumnBindingDialog(true);
					dialog.setInput(inputElement);
					dialog.setExpressionProvider(expressionProvider);
					dialog.setAggreate(true);
					if (dialog.open() == Dialog.OK) {
						if (bindingTable != null) {
							refreshBindingTable();
							bindingTable.getTable().setSelection(bindingTable.getTable().getItemCount() - 1);
						}
					}

					refreshBindingTable();
					if (table.getItemCount() > 0) {
						setSelectionInTable(table.getItemCount() - 1);
					}
					updateButtons();
				}

			});
		}

		btnEdit = new Button(contentComposite, SWT.PUSH);
		btnEdit.setText(MSG_EDIT);
		data = new GridData();
		data.widthHint = Math.max(60, btnEdit.computeSize(SWT.DEFAULT, SWT.DEFAULT, true).x);
		btnEdit.setLayoutData(data);
		btnEdit.addSelectionListener(new SelectionAdapter() {

			@Override
			public void widgetSelected(SelectionEvent e) {
				handleEditEvent();
				refreshBindingTable();
			}

		});
		btnDel = new Button(contentComposite, SWT.PUSH);
		btnDel.setText(MSG_DELETE);
		data = new GridData();
		data.widthHint = Math.max(60, btnDel.computeSize(SWT.DEFAULT, SWT.DEFAULT, true).x);
		btnDel.setLayoutData(data);
		btnDel.addSelectionListener(new SelectionAdapter() {

			@Override
			public void widgetSelected(SelectionEvent e) {
				if (bindingTable.isCellEditorActive()) {
					bindingTable.cancelEditing();
				}
				int pos = bindingTable.getTable().getSelectionIndex();
				if (pos == -1) {
					bindingTable.getTable().setFocus();
					return;
				}
				selectIndex = pos;
				int itemCount = bindingTable.getTable().getItemCount();
				if (selectIndex == itemCount - 1) {
					selectIndex--;
				}
				try {
					handleDelEvent();
				} catch (Exception e1) {
					WidgetUtil.processError(getShell(), e1);
				}
				refreshBindingTable();
			}
		});

		// initTableCellColor( );

		// Add custom buttons
		int buttonsNumber = addButtons(contentComposite, table);
		if (buttonsNumber > 0) {
			// Adjust UI layout
			if (table.getLayoutData() instanceof GridData) {
				((GridData) table.getLayoutData()).verticalSpan += buttonsNumber;
			}
		}

		if (!isDataSetVisible) {
			if (composite != null) {
				((GridData) composite.getLayoutData()).exclude = true;
			}
		}

		return parentComposite;
	}

	protected void deleteRow(ComputedColumnHandle handle) {
		try {
			if (handle.getName().equals(selectedColumnName)) {
				selectedColumnName = null;
			}
			handle.drop();
		} catch (PropertyValueException e) {
			ExceptionHandler.handle(e);
		}
	}

	private void generateBindingColumns() throws SemanticException {
		List columnList = DataUtil.generateComputedColumns(inputElement);
		if (columnList.size() > 0) {
			for (Iterator iter = columnList.iterator(); iter.hasNext();) {
				addBinding((ComputedColumn) iter.next());
			}
		}
		if (inputElement != null && inputElement.getDataSet() != null) {
			generateOutputParmsBindings(inputElement.getDataSet());
		}
		refreshBindingTable();
	}

	/**
	 * Gets the DE CommandStack instance
	 *
	 * @return CommandStack instance
	 */
	private CommandStack getActionStack() {
		return SessionHandleAdapter.getInstance().getCommandStack();
	}

	public String[] getAvailableDatasetItems() {
		String[] dataSets = ChoiceSetFactory.getDataSets();
		String[] newList = new String[dataSets.length + 1];
		newList[0] = NullDatasetChoice;
		System.arraycopy(dataSets, 0, newList, 1, dataSets.length);
		return newList;
	}

	protected List getBindingList(DesignElementHandle inputElement) {
		List elementsList = DEUtil.getVisiableColumnBindingsList(inputElement);
		if (this.filterSelf) {
			Iterator iterator = this.inputElement.columnBindingsIterator();

			while (iterator.hasNext()) {
				Object obj = iterator.next();
				System.out.println(obj);
				elementsList.remove(obj);
			}
		}
		return elementsList;
	}

	private String getColumnName(String expression) {
		List columnList = DEUtil.getVisiableColumnBindingsList(inputElement);
		for (Iterator iter = columnList.iterator(); iter.hasNext();) {
			ComputedColumnHandle cachedColumn = (ComputedColumnHandle) iter.next();
			String columnName = cachedColumn.getName();
			if (LinkedDataSetUtil.bindToLinkedDataSet(inputElement)
					? DEUtil.getDataExpression(columnName).equals(expression)
					: DEUtil.getColumnExpression(columnName).equals(expression)) {
				return columnName;
			}
		}

		return null;
	}

	private String getDataSetName() {
		if (inputElement.getDataSet() == null) {
			return null;
		}
		String dataSetName = inputElement.getDataSet().getQualifiedName();
		if (StringUtil.isBlank(dataSetName)) {
			dataSetName = null;
		}
		return dataSetName;
	}

	protected Map<String, ReportItemHandle> referMap = new HashMap<>();

	private Button btnAddAggr;

	private Button btnRefresh;

	protected String[] getReferences() {
		List referenceList = inputElement.getAvailableDataSetBindingReferenceList();
		String[] references = new String[referenceList.size() + 1];
		references[0] = NullReportItemChoice;
		referMap.put(references[0], null);
		int j = 0;
		for (int i = 0; i < referenceList.size(); i++) {
			ReportItemHandle item = ((ReportItemHandle) referenceList.get(i));
			if (item.getName() != null) {
				references[++j] = item.getQualifiedName();
				referMap.put(references[j], item);
			}
		}
		int tmp = j + 1;
		Arrays.sort(references, 1, tmp);
		for (int i = 0; i < referenceList.size(); i++) {
			ReportItemHandle item = ((ReportItemHandle) referenceList.get(i));
			if (item.getName() == null) {
				references[++j] = item.getElement().getDefn().getDisplayName() + " (ID " //$NON-NLS-1$
						+ item.getID() + ") - " //$NON-NLS-1$
						+ Messages.getString("BindingPage.ReportItem.NoName"); //$NON-NLS-1$
				referMap.put(references[j], item);
			}
		}
		Arrays.sort(references, tmp, referenceList.size() + 1);
		return references;
	}

	private ComputedColumnHandle getSelectColumnHandle() {
		if (selectedColumnName != null) {
			for (int i = 0; i < bindingTable.getTable().getItemCount(); i++) {
				ComputedColumnHandle handle = (ComputedColumnHandle) bindingTable.getElementAt(i);
				if (selectedColumnName.equals(handle.getName())) {
					return handle;
				}
			}
		}
		return null;
	}

	protected void handleAddEvent() {
		DataColumnBindingDialog dialog = new DataColumnBindingDialog(true);
		dialog.setInput(inputElement);
		dialog.setExpressionProvider(expressionProvider);
		if (dialog.open() == Dialog.OK) {
			if (bindingTable != null) {
				refreshBindingTable();
			}
		}

	}

	protected void handleDelEvent() {
		if (!btnDel.isEnabled()) {
			return;
		}
		int pos = bindingTable.getTable().getSelectionIndex();
		pos = getOriginalIndex(pos);
		if (pos > -1) {
			try {
				ComputedColumnHandle handle = (ComputedColumnHandle) (DEUtil.getBindingHolder(inputElement))
						.getColumnBindings().getAt(pos);
				deleteRow(handle);
			} catch (Exception e1) {
				ExceptionHandler.handle(e1);
			}
		}
	}

	protected void handleEditEvent() {
		int pos = bindingTable.getTable().getSelectionIndex();
		editSelectedBinding(pos);
	}

	/**
	 * Edits the selected binding of table.
	 *
	 * @param bindingIndex
	 */
	private void editSelectedBinding(int bindingIndex) {
		if (!btnEdit.isEnabled()) {
			return;
		}
		ComputedColumnHandle bindingHandle = null;
		bindingIndex = getOriginalIndex(bindingIndex);
		if (bindingIndex > -1) {
			bindingHandle = (ComputedColumnHandle) (DEUtil.getBindingHolder(inputElement)).getColumnBindings()
					.getAt(bindingIndex);
		}
		if (bindingHandle == null) {
			return;
		}

		String bindingName = bindingHandle.getName();
		DataColumnBindingDialog dialog = new DataColumnBindingDialog(false);
		setDialogInput(dialog, bindingHandle);
		dialog.setExpressionProvider(expressionProvider);
		if (dialog.open() == Dialog.OK) {
			if (bindingTable != null) {
				bindingTable.getTable().setSelection(bindingIndex);
			}
			if (selectedColumnName != null && selectedColumnName.equals(bindingName)) {
				selectedColumnName = bindingHandle.getName();
			}
		}
		selectIndex = getShowIndex(bindingIndex);
	}

	protected void setDialogInput(DataColumnBindingDialog dialog, ComputedColumnHandle bindingHandle) {
		if (dialog != null) {
			dialog.setInput(inputElement, bindingHandle);
		}
	}

	@Override
	protected boolean initDialog() {
		if (canSelect) {
			if (inputElement instanceof DataItemHandle) {
				selectedColumnName = ((DataItemHandle) inputElement).getResultSetColumn();
				updateSelection();
			} else if (inputElement instanceof ImageHandle) {
				selectedColumnName = getColumnName(((ImageHandle) inputElement).getValueExpression());
				updateSelection();
			}
		}
		load();
		return super.initDialog();
	}

	@Override
	protected boolean needRememberLastSize() {
		return true;
	}

	/**
	 * @return Returns the enableAutoCommit.
	 */
	public boolean isEnableAutoCommit() {
		return enableAutoCommit;
	}

	public void load() {
		if (canSelect) {
			datasetRadio.setEnabled(true);
			reportItemRadio.setEnabled(true);
			BindingInfo info = (BindingInfo) loadValue();
			if (info != null) {
				refreshBindingInfo(info);
			}
		}
		refreshBindingTable();
	}

	public Object loadValue() {
		if (canSelect) {
			int type = inputElement.getDataBindingType();
			Object value;
			if (type == ReportItemHandle.DATABINDING_TYPE_NONE) {
				type = DEUtil.getBindingHolder(inputElement).getDataBindingType();
			}
			switch (type) {
			case ReportItemHandle.DATABINDING_TYPE_DATA:
				DataSetHandle dataset = inputElement.getDataSet();
				if (dataset == null) {
					value = NullDatasetChoice;
				} else {
					value = dataset.getQualifiedName();
				}
				break;
			case ReportItemHandle.DATABINDING_TYPE_REPORT_ITEM_REF:
				ReportItemHandle reference = inputElement.getDataBindingReference();
				if (reference == null) {
					value = NullReportItemChoice;
				} else {
					value = reference.getQualifiedName();
				}
				break;
			default:
				value = NullDatasetChoice;
			}
			BindingInfo info = new BindingInfo(type, value);
			return info;
		}
		return null;
	}

	@Override
	protected void okPressed() {
		if (canSelect) {
			setResult(selectedColumnName);
			if (inputElement instanceof DataItemHandle) {
				try {
					((DataItemHandle) inputElement).setResultSetColumn(selectedColumnName);
				} catch (SemanticException e) {
					ExceptionHandler.handle(e);
				}
			}
		}
		if (getSelectColumnHandle() != null && ExtendedDataModelUIAdapterHelper.isBoundToExtendedData(inputElement)) {
			DataModelAdapterStatus status = DataModelAdapterUtil.validateRelativeTimePeriod(inputElement,
					getSelectColumnHandle());
			if (status.getStatus() == DataModelAdapterStatus.Status.FAIL) {
				MessageDialog.openError(UIUtil.getDefaultShell(), null, status.getMessage());
				return;
			}
		}
		super.okPressed();
	}

	private void refreshBinding() {
		if (datasetRadio.getSelection()) {
			datasetRadio.setSelection(true);
			datasetCombo.setEnabled(true);
			reportItemRadio.setSelection(false);
			reportItemCombo.setEnabled(false);
			if (datasetCombo.getSelectionIndex() == -1) {
				datasetCombo.setItems(getAvailableDatasetItems());
				datasetCombo.select(0);
			}
		} else {
			datasetRadio.setSelection(false);
			datasetCombo.setEnabled(false);
			reportItemRadio.setSelection(true);
			reportItemCombo.setEnabled(true);
			if (reportItemCombo.getSelectionIndex() == -1) {
				reportItemCombo.setItems(getReferences());
				reportItemCombo.select(0);
			}
		}
	}

	private BindingInfo oldInfo;

	private void refreshBindingInfo(BindingInfo info) {
		if (canSelect) {
			int type = info.getBindingType();
			Object value = info.getBindingValue();
			datasetCombo.setItems(getAvailableDatasetItems());
			reportItemCombo.setItems(getReferences());
			if (type == ReportItemHandle.DATABINDING_TYPE_NONE) {
				type = DEUtil.getBindingHolder(inputElement).getDataBindingType();
			}
			switch (type) {
			case ReportItemHandle.DATABINDING_TYPE_NONE:
				if (oldInfo != null) {
					if (oldInfo.getBindingType() == ReportItemHandle.DATABINDING_TYPE_DATA) {
						selectDatasetType(value);
					} else if (oldInfo.getBindingType() == ReportItemHandle.DATABINDING_TYPE_REPORT_ITEM_REF) {
						selectReferenceType(value);
					}
					break;
				}
			case ReportItemHandle.DATABINDING_TYPE_DATA:
				selectDatasetType(value);
				break;
			case ReportItemHandle.DATABINDING_TYPE_REPORT_ITEM_REF:
				selectReferenceType(value);
			}
		}
	}

	private void selectReferenceType(Object value) {
		datasetRadio.setSelection(false);
		datasetCombo.setEnabled(false);
		reportItemRadio.setSelection(true);
		reportItemCombo.setEnabled(true);
		reportItemCombo.setText(value.toString());
	}

	private void selectDatasetType(Object value) {
		datasetRadio.setSelection(true);
		datasetCombo.setEnabled(true);
		datasetCombo.setText(value.toString());
		reportItemRadio.setSelection(false);
		reportItemCombo.setEnabled(false);
	}

	protected void refreshBindingTable() {
		bindingTable.refresh();
		if (canSelect) {
			updateSelection();
		}
		updateButtons();
	}

	private void resetDataSetReference(Object value, boolean clearHistory) {
		try {
			startTrans(""); //$NON-NLS-1$
			inputElement.setDataBindingReference(null);
			DataSetHandle dataSet = null;
			if (value != null) {
				dataSet = SessionHandleAdapter.getInstance().getReportDesignHandle().findDataSet(value.toString());
			}
			if (inputElement.getDataBindingType() == ReportItemHandle.DATABINDING_TYPE_REPORT_ITEM_REF) {
				inputElement.setDataBindingReference(null);
			}
			boolean isExtendedDataModel = false;
			if (dataSet == null && value != null) {
				inputElement.setDataSet(null);
				isExtendedDataModel = new LinkedDataSetAdapter().setLinkedDataModel(inputElement, value.toString());
			} else {
				new LinkedDataSetAdapter().setLinkedDataModel(inputElement, null);
				inputElement.setDataSet(dataSet);
			}

			if (clearHistory) {
				inputElement.getColumnBindings().clearValue();
				inputElement.getPropertyHandle(ReportItemHandle.PARAM_BINDINGS_PROP).clearValue();
			}
			if (!isExtendedDataModel) {
				generateBindingColumns();
			}

			selectedColumnName = null;
			commit();
		} catch (SemanticException e) {
			rollback();
			ExceptionHandler.handle(e);
		}
		load();
	}

	private void resetReference(Object value) {
		if (value == null && inputElement.getDataBindingType() == ReportItemHandle.DATABINDING_TYPE_DATA) {
			resetDataSetReference(null, true);
		} else {
			try {
				startTrans(Messages.getString("DataColumBindingDialog.stackMsg.resetReference")); //$NON-NLS-1$
				ReportItemHandle element = null;
				if (value != null) {
					element = (ReportItemHandle) SessionHandleAdapter.getInstance().getReportDesignHandle()
							.findElement(value.toString());
				}
				inputElement.setDataBindingReference(element);
				selectedColumnName = null;
				commit();
			} catch (SemanticException e) {
				rollback();
				ExceptionHandler.handle(e);
			}
			load();
		}
	}

	private void rollback() {
		if (isEnableAutoCommit()) {
			getActionStack().rollback();
		}
	}

	public void save(Object saveValue) throws SemanticException {
		if (saveValue instanceof BindingInfo) {
			BindingInfo info = (BindingInfo) saveValue;
			int type = info.getBindingType();
			String value = info.getBindingValue().toString();
			switch (type) {
			case ReportItemHandle.DATABINDING_TYPE_DATA:
				if (value.equals(NullDatasetChoice)) {
					value = null;
				}
				int ret = 0;
				if (!NullDatasetChoice.equals(((BindingInfo) loadValue()).getBindingValue().toString())
						|| inputElement.getColumnBindings().iterator().hasNext()) {
					MessageDialog prefDialog = new MessageDialog(UIUtil.getDefaultShell(),
							Messages.getString("dataBinding.title.changeDataSet"), //$NON-NLS-1$
							null, Messages.getString("dataBinding.message.changeDataSet"), //$NON-NLS-1$
							MessageDialog.QUESTION,
							new String[] { Messages.getString("AttributeView.dialg.Message.Yes"), //$NON-NLS-1$
									Messages.getString("AttributeView.dialg.Message.No"), //$NON-NLS-1$
									Messages.getString("AttributeView.dialg.Message.Cancel") }, //$NON-NLS-1$
							0);

					ret = prefDialog.open();
				}

				switch (ret) {
				// Clear binding info
				case 0:
					resetDataSetReference(value, true);
					break;
				// Doesn't clear binding info
				case 1:
					resetDataSetReference(value, false);
					break;
				// Cancel.
				case 2:
					load();
				}
				break;
			case ReportItemHandle.DATABINDING_TYPE_REPORT_ITEM_REF:
				if (value.equals(NullReportItemChoice)) {
					value = null;
				} else if (referMap.get(value).getName() == null) {
					MessageDialog dialog = new MessageDialog(UIUtil.getDefaultShell(),
							Messages.getString("dataBinding.title.haveNoName"), //$NON-NLS-1$
							null, Messages.getString("dataBinding.message.haveNoName"), //$NON-NLS-1$
							MessageDialog.QUESTION, new String[] { Messages.getString("dataBinding.button.OK")//$NON-NLS-1$
							}, 0);

					dialog.open();
					load();
					return;
				}
				int ret1 = 0;
				if (!NullReportItemChoice.equals(((BindingInfo) loadValue()).getBindingValue().toString())
						|| inputElement.getColumnBindings().iterator().hasNext()) {
					MessageDialog prefDialog = new MessageDialog(UIUtil.getDefaultShell(),
							Messages.getString("dataBinding.title.changeDataSet"), //$NON-NLS-1$
							null, Messages.getString("dataBinding.message.changeReference"), //$NON-NLS-1$
							MessageDialog.QUESTION,
							new String[] { Messages.getString("AttributeView.dialg.Message.Yes"), //$NON-NLS-1$
									Messages.getString("AttributeView.dialg.Message.Cancel") }, //$NON-NLS-1$
							0);

					ret1 = prefDialog.open();
				}

				switch (ret1) {
				// Clear binding info
				case 0:
					resetReference(value);
					break;
				// Cancel.
				case 1:
					load();
				}
			}
		}
	}

	private void saveBinding() {
		BindingInfo info = new BindingInfo();
		if (datasetRadio.getSelection()) {
			info.setBindingType(ReportItemHandle.DATABINDING_TYPE_DATA);
			info.setBindingValue(datasetCombo.getText());
		} else {
			info.setBindingType(ReportItemHandle.DATABINDING_TYPE_REPORT_ITEM_REF);
			info.setBindingValue(reportItemCombo.getText());
		}
		try {
			this.oldInfo = info;
			save(info);
		} catch (SemanticException e) {
			ExceptionHandler.handle(e);
		}
	}

	/**
	 * @param enableAutoCommit The enableAutoCommit to set.
	 */
	public void setEnableAutoCommit(boolean enableAutoCommit) {
		this.enableAutoCommit = enableAutoCommit;
	}

	public void setExpressionProvider(ExpressionProvider provider) {
		expressionProvider = provider;
	}

	/*
	 * Set data for Group List
	 */
	public void setGroupList(List groupList) {
		this.groupList = groupList;
	}

	/*
	 * Set input for dialog
	 */
	private void setInput(ReportItemHandle input) {
		this.inputElement = input;
		ReportItemHandle container = DEUtil.getBindingHolder(input.getContainer());
		if (container != null && (container.getDataSet() != null || container.columnBindingsIterator().hasNext())) {
			NullDatasetChoice = CHOICE_DATASET_FROM_CONTAINER;
		} else {
			NullDatasetChoice = CHOICE_NONE;
		}

		if (container != null && container.getDataBindingReference() != null) {
			NullReportItemChoice = CHOICE_REPORTITEM_FROM_CONTAINER;
		} else {
			NullReportItemChoice = CHOICE_NONE;
		}

		isDataSetVisible = DEUtil.getBindingHolder(inputElement).getElement().getDefn()
				.isPropertyVisible(IReportItemModel.DATA_SET_PROP);

		IBindingDialogHelper dialogHelper = (IBindingDialogHelper) ElementAdapterManager.getAdapter(inputElement,
				IBindingDialogHelper.class);
		if (dialogHelper != null) {
			IBindingDialogHelper helperHelper = (IBindingDialogHelper) ElementAdapterManager.getAdapter(dialogHelper,
					IBindingDialogHelper.class);
			if (helperHelper != null) {
				dialogHelper = helperHelper;
			}
			dialogHelper.setBindingHolder(DEUtil.getBindingHolder(inputElement));
		}
		canAggregate = dialogHelper == null ? false : dialogHelper.canProcessAggregation();
	}

	protected void setSelectionInTable(int selectedIndex) {
		this.selectIndex = selectedIndex;
	}

	private void startTrans(String name) {
		if (isEnableAutoCommit()) {
			getActionStack().startTrans(name);
		}
	}

	protected void updateButtons() {
		boolean okEnable = false;

		if (!canSelect || (!isDataSetVisible && selectedColumnName != null)
		// || ( selectedColumnName != null && getDataSetName( ) != null )
		// || ( selectedColumnName != null && DEUtil.getBindingHolder(
		// inputElement )
		// .getDataSet( ) != null )
				|| getSelectColumnHandle() != null) {
			okEnable = true;
		}
		getOkButton().setEnabled(okEnable);
		int min = 0;
		int max = bindingTable.getTable().getItemCount() - 1;

		if ((min <= selectIndex) && (selectIndex <= max)) {
			btnDel.setEnabled(true);
			if (btnEdit != null) {
				btnEdit.setEnabled(true);
			}
		} else {
			btnDel.setEnabled(false);
			if (btnEdit != null) {
				btnEdit.setEnabled(false);
			}
		}
		bindingTable.getTable().select(selectIndex);
		if (DEUtil.getBindingHolder(inputElement).getDataBindingType() == ReportItemHandle.DATABINDING_TYPE_DATA) {
			btnAdd.setEnabled(true);
			if (btnAddAggr != null) {
				btnAddAggr.setEnabled(true);
			}
			if (btnRefresh != null) {
				btnRefresh.setEnabled(true);
			}
		} else if (DEUtil.getBindingHolder(inputElement).getDataBindingType() == ReportItemHandle.DATABINDING_TYPE_NONE
				&& (DEUtil.getBindingHolder(inputElement, true) == null || DEUtil.getBindingHolder(inputElement, true)
						.getDataBindingType() != ReportItemHandle.DATABINDING_TYPE_REPORT_ITEM_REF)) {
			btnAdd.setEnabled(true);
			if (btnAddAggr != null) {
				btnAddAggr.setEnabled(true);
			}
			if (btnRefresh != null) {
				btnRefresh.setEnabled(true);
			}
		} else {
			btnAdd.setEnabled(false);
			btnEdit.setEnabled(false);
			btnDel.setEnabled(false);
			if (btnAddAggr != null) {
				btnAddAggr.setEnabled(false);
			}
			if (btnRefresh != null) {
				btnRefresh.setEnabled(false);
			}
		}
	}

	private void updateSelection() {
		if (canSelect) {
			((CheckboxTableViewer) bindingTable).setAllChecked(false);
			((CheckboxTableViewer) bindingTable).setGrayed(dummyChoice, true);
			if (getSelectColumnHandle() != null) {
				((CheckboxTableViewer) bindingTable).setChecked(getSelectColumnHandle(), true);
			}
		}
	}

	protected Button getAggregationButton() {
		return btnAddAggr;
	}

	private int sortingColumnIndex;

	public void setSortingColumnIndex(int index) {
		this.sortingColumnIndex = index;
	}

	private int sortDirection = SWT.UP;

	public void setSortDirection(int dir) {
		sortDirection = dir;
	}

}
